use e_utils::chrono::{DateTime, TimeZone, Utc};
use std::fmt;

// NTP与UNIX时间戳差值保持不变（1900-01-01到1970-01-01）
pub static EPOCH_DELTA: i64 = 2208988800i64;
static NTP_SCALE: f64 = 4294967295.0_f64;

#[derive(Debug, PartialEq, Default, Copy, Clone)]
pub struct ShortFormat {
    pub sec: u16,
    pub frac: u16,
}

#[derive(Debug, PartialEq, Default, Copy, Clone)]
pub struct TimestampFormat {
    pub sec: u32,
    pub frac: u32,
}
impl TimestampFormat {
    pub fn now() -> Self {
        let now = e_utils::chrono::Utc::now();
        let sec = now.timestamp() + EPOCH_DELTA; // 添加 NTP 与 UNIX 时间差
        let frac = (now.timestamp_subsec_nanos() as f64 * NTP_SCALE / 1e9) as u32;
        TimestampFormat {
            sec: sec as u32,
            frac,
        }
    }
}
// 核心修改点1：时间类型替换为chrono的DateTime<Utc>
impl From<ShortFormat> for DateTime<Utc> {
    fn from(t: ShortFormat) -> Self {
        let total_secs = t.sec as i64 - EPOCH_DELTA;
        let nanos = (t.frac as f64 / NTP_SCALE * 1e9) as u32;
        Utc.timestamp_opt(total_secs, nanos).unwrap()
    }
}

impl From<DateTime<Utc>> for ShortFormat {
    fn from(dt: DateTime<Utc>) -> Self {
        let sec = (dt.timestamp() + EPOCH_DELTA) as u16;
        let frac = (dt.timestamp_subsec_nanos() as f64 * NTP_SCALE / 1e9) as u16;
        ShortFormat { sec, frac }
    }
}

// 核心修改点2：格式化实现改用chrono的format方法
impl fmt::Display for ShortFormat {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let dt: DateTime<Utc> = (*self).into();
        write!(f, "{}", dt.format("%a %b %e %T %Y")) // 等效原asctime格式[1](@ref)
    }
}

// 数值转换保持相同逻辑
impl From<ShortFormat> for u32 {
    fn from(t: ShortFormat) -> u32 {
        (t.sec as u32) << 16 | t.frac as u32
    }
}

impl From<u32> for ShortFormat {
    fn from(t: u32) -> ShortFormat {
        ShortFormat {
            sec: (t >> 16) as u16,
            frac: t as u16,
        }
    }
}

// 长格式时间结构体实现
impl From<TimestampFormat> for DateTime<Utc> {
    fn from(t: TimestampFormat) -> Self {
        let total_secs = t.sec as i64 - EPOCH_DELTA;
        let nanos = (t.frac as f64 / NTP_SCALE * 1e9) as u32;
        Utc.timestamp_opt(total_secs, nanos).unwrap()
    }
}

impl From<DateTime<Utc>> for TimestampFormat {
    fn from(dt: DateTime<Utc>) -> Self {
        let sec = (dt.timestamp() + EPOCH_DELTA) as u32;
        let frac = (dt.timestamp_subsec_nanos() as f64 * NTP_SCALE / 1e9) as u32;
        TimestampFormat { sec, frac }
    }
}

impl fmt::Display for TimestampFormat {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let dt: DateTime<Utc> = (*self).into();
        write!(f, "{}", dt.format("%a %b %e %T %Y"))
    }
}

impl From<TimestampFormat> for u64 {
    fn from(t: TimestampFormat) -> u64 {
        (t.sec as u64) << 32 | t.frac as u64
    }
}

impl From<u64> for TimestampFormat {
    fn from(t: u64) -> TimestampFormat {
        TimestampFormat {
            sec: (t >> 32) as u32,
            frac: t as u32,
        }
    }
}

// 测试用例改造
#[test]
fn timestamp_conversions() {
    // 测试当前时间转换
    let chrono_now = Utc::now();

    // 短格式测试
    let short_format: ShortFormat = chrono_now.into();
    let converted_back: DateTime<Utc> = short_format.into();
    assert!(
        (chrono_now - converted_back)
            .num_nanoseconds()
            .unwrap()
            .abs()
            < 1000
    );

    // 长格式测试
    let ts_format: TimestampFormat = chrono_now.into();
    let converted_back: DateTime<Utc> = ts_format.into();
    assert!(
        (chrono_now - converted_back)
            .num_nanoseconds()
            .unwrap()
            .abs()
            < 1000
    );
}
